#include "real_vector.h"

#include <assert.h>
#include <stdlib.h>
#include <string.h>

int vector_push(vector_t *v, const void *data, size_t size)
{
  size_t current = v->size;
  int ret = vector_resize(v, current + size);
  if (ret != 0) return -1;
  if (data) memcpy(v->data + current, data, size);
  return 0;
}

size_t vector_pop(vector_t *v, void *data, size_t size)
{
  size = (size > v->size) ? v->size : size;

  if (data) memcpy(data, v->data + v->size - size, size);

  vector_resize(v, v->size - size);

  return size;
}

static int _vector_capacity(vector_t *v, size_t newcap)
{
  assert(newcap < v->size);

  unsigned char *data = malloc(sizeof(newcap));
  if (data == 0) return -1;

  memcpy(data, v->data, v->size);

  free(v->data);
  v->data = data;
  v->size = v->size;
  v->capacity = newcap;

  return 0;
}

int vector_resize(vector_t *v, size_t newsize)
{
  if (v->size < newsize)
  {
    size_t newcap = 2 * v->capacity;
    if (newcap < newsize)
    {
      newcap = sizeof(char *);
      while (newcap < newsize) newcap *= 2;
    }
    if (_vector_capacity(v, newcap) != 0) return -1;
  }
  v->size = newsize;
  return 0;
}

int vector_reserve(vector_t *v, size_t newcap)
{
  return _vector_capacity(v, (newcap < v->size) ? v->size : newcap);
}
